import streamlit as st
import pandas as pd
import os
import sys

# 添加项目根目录到Python路径
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

# 导入自定义模块
from data.fetcher import FinancialDataFetcher
from data.processor import FinancialDataProcessor
from visualization.charts import FinancialCharts
from config.settings import APP, DEFAULT_STOCK, DATA_STORAGE
from config.mapping import get_ordered_categories, CATEGORY_MAPPING

# 设置页面配置
st.set_page_config(
    page_title=APP["title"],
    page_icon="📊",
    layout="wide",
    initial_sidebar_state="expanded"
)

# 初始化数据获取器、处理器和图表生成器
fetcher = FinancialDataFetcher(data_dir=DATA_STORAGE["raw_data_dir"])
processor = FinancialDataProcessor()
charts = FinancialCharts()

# 页面标题
st.title(APP["title"])
st.markdown(APP["description"])

# 侧边栏 - 数据输入区域
with st.sidebar:
    st.header("数据输入")
    
    # 股票代码输入
    stock_code = st.text_input("股票代码", DEFAULT_STOCK["code"], help="输入6位股票代码，如：000001")
    
    # 报告类型选择
    report_type = st.radio(
        "报告类型",
        options=["年报", "半年报", "一季报", "三季报"],
        index=0,
        help="选择要查看的报告类型"
    )
    
    # 获取数据按钮
    if st.button("获取数据"):
        if not stock_code or len(stock_code) != 6:
            st.error("请输入正确的6位股票代码")
        else:
            with st.spinner("正在获取数据，请稍候..."):
                # 获取资产负债表数据
                try:
                    st.info(f"正在获取股票 {stock_code} 的{report_type}数据...")
                    
                    # 获取原始数据
                    raw_data = fetcher.fetch_balance_sheet(stock_code, report_type)
                    
                    if raw_data is not None and not raw_data.empty:
                        st.info(f"原始数据获取成功，形状: {raw_data.shape}")
                        
                        # 保存原始数据
                        raw_file_path = fetcher.save_to_local(raw_data, stock_code, report_type)
                        st.info(f"原始数据已保存到: {raw_file_path}")
                        
                        # 按自定义分类处理数据
                        st.info("正在进行数据分类处理...")
                        categorized_data = processor.categorize_data(raw_data)
                        
                        if categorized_data is not None and not categorized_data.empty:
                            st.info(f"数据分类成功，形状: {categorized_data.shape}")
                            
                            # 保存分类后的数据
                            processed_file_path = os.path.join(
                                DATA_STORAGE["processed_data_dir"],
                                f"{stock_code}_{report_type}_categorized.csv"
                            )
                            processor.save_categorized_data(categorized_data, processed_file_path)
                            st.info(f"分类数据已保存到: {processed_file_path}")
                            
                            # 将数据保存到会话状态
                            st.session_state["raw_data"] = raw_data
                            st.session_state["categorized_data"] = categorized_data
                            st.session_state["stock_code"] = stock_code
                            st.session_state["report_type"] = report_type
                            
                            st.success("数据获取和处理成功！")
                        else:
                            st.error("数据分类处理失败，请检查原始数据格式或查看控制台日志")
                            st.info("原始数据预览:")
                            st.dataframe(raw_data.head())
                    else:
                        st.error("获取数据失败，请检查股票代码是否正确")
                        st.info("可能的原因:")
                        st.markdown("1. 股票代码不存在或已退市")
                        st.markdown("2. 新浪财经数据源暂无该股票数据")
                        st.markdown("3. 网络连接问题")
                        st.markdown("4. AKShare接口变更")
                        st.markdown("请查看控制台日志获取详细错误信息")
                except Exception as e:
                    import traceback
                    error_details = traceback.format_exc()
                    st.error(f"获取数据时发生错误: {e}")
                    st.info("错误详情:")
                    st.code(error_details)
    
    # 显示数据来源信息
    st.markdown("---")
    st.caption("数据来源: 新浪财经 (通过AKShare获取)")
    st.caption(f"版本: {APP['version']}")

# 主页面 - 数据展示区域
# 检查是否有数据可以展示
if "categorized_data" in st.session_state and not st.session_state["categorized_data"].empty:
    # 获取会话中的数据
    categorized_data = st.session_state["categorized_data"]
    raw_data = st.session_state["raw_data"]
    stock_code = st.session_state["stock_code"]
    report_type = st.session_state["report_type"]
    
    # 创建选项卡
    tab1, tab2, tab3 = st.tabs(["柱状图", "原始数据", "分类数据"])
    
    with tab1:
        st.header(f"{stock_code} - {report_type} 财务结构分析")
        
        # 处理原始数据，提取每个记录作为单独的数据帧
        raw_records = []
        raw_periods = []
        
        if raw_data is not None and not raw_data.empty:
            # 检查是否有报告日列
            date_col = None
            if '报告日' in raw_data.columns:
                date_col = '报告日'
            elif '报告日期' in raw_data.columns:
                date_col = '报告日期'
            
            # 如果有报告日列，则按报告日分组处理每条记录
            if date_col is not None:
                # 获取唯一的报告日期
                unique_dates = raw_data[date_col].unique()
                
                # 对每个报告日期创建一个处理后的数据帧
                for date in unique_dates:
                    # 提取该日期的数据
                    date_data = raw_data[raw_data[date_col] == date].copy()
                    
                    # 使用处理器处理该日期的数据
                    processor = FinancialDataProcessor()
                    processed_data = processor.categorize_data(date_data)
                    
                    if processed_data is not None and not processed_data.empty:
                        raw_records.append(processed_data)
                        # 格式化日期显示
                        formatted_date = str(date)
                        if len(formatted_date) == 8 and formatted_date.isdigit():
                            formatted_date = f"{formatted_date[:4]}-{formatted_date[4:6]}-{formatted_date[6:]}"
                        raw_periods.append(formatted_date)
            else:
                # 如果没有报告日列，则使用原始的分类数据
                raw_records = [categorized_data]
                raw_periods = [report_type]
        else:
            # 如果没有原始数据，则使用原始的分类数据
            raw_records = [categorized_data]
            raw_periods = [report_type]
        
        # 添加记录选择器
        if len(raw_records) > 1:
            st.write("### 选择报告期")
            selected_index = st.slider("左右滑动切换不同记录", 0, len(raw_records)-1, 0)
            st.write(f"当前显示: {raw_periods[selected_index]}")
            
            # 创建柱状图 - 显示选定的单条记录
            fig = charts.create_category_bar_chart(
                raw_records[selected_index],
                company_name=stock_code,
                report_date=raw_periods[selected_index]
            )
        else:
            # 只有一条记录时直接显示
            fig = charts.create_category_bar_chart(
                categorized_data,
                company_name=stock_code,
                report_date=report_type
            )
        
        if fig is not None:
            # 显示图表
            st.plotly_chart(fig, use_container_width=True)
            
            # 添加图表说明
            st.markdown("### 图表说明")
            st.markdown("本图表按自定义科目分类展示公司财务结构，单位为亿元。")
            st.markdown("鼠标悬停可查看具体数值和占比。")
            
            # 添加分类说明
            st.markdown("### 分类说明")
            for category in get_ordered_categories():
                st.markdown(f"**{category}** ({CATEGORY_MAPPING[category]['description']}): {', '.join(CATEGORY_MAPPING[category]['items'][:3])}{'...' if len(CATEGORY_MAPPING[category]['items']) > 3 else ''}")
        else:
            st.error("无法创建图表，请检查数据")
    
    with tab2:
        st.header("原始财务数据")
        if raw_data is not None and not raw_data.empty:
            st.dataframe(raw_data, use_container_width=True)
        else:
            st.error("无原始数据可显示")
    
    with tab3:
        st.header("分类后的财务数据")
        if categorized_data is not None and not categorized_data.empty:
            st.dataframe(categorized_data, use_container_width=True)
        else:
            st.error("无分类数据可显示")

else:
    # 显示欢迎信息和使用说明
    st.info("👈 请在左侧输入股票代码并选择报告类型，然后点击'获取数据'按钮")
    
    # 显示示例图片或使用说明
    st.markdown("### 使用说明")
    st.markdown("""
    1. 在左侧输入6位股票代码（如：000001）
    2. 选择要查看的报告类型（年报、半年报等）
    3. 点击"获取数据"按钮
    4. 系统将自动获取并处理数据，然后展示财务结构柱状图
    5. 可以切换到"原始数据"和"分类数据"选项卡查看详细数据
    """)
    
    # 显示功能特点
    st.markdown("### 功能特点")
    st.markdown("""
    - **数据自动化**: 一键获取并整理财务数据，减少人工操作
    - **自定义分类**: 按照专业财务分析逻辑重组数据
    - **可视化分析**: 直观展示财务结构，降低理解门槛
    - **本地存储**: 自动保存数据副本，方便后续分析
    """)

# 运行说明（在页面底部）
st.markdown("---")
st.caption("本应用基于Python和Streamlit开发，使用AKShare获取数据")
st.caption(f"© {APP['author']} {APP['version']}")